<?php
class Controller_Vote extends Controller_Base{
	public function __construct(){
		parent::__construct();
		parent::checkLogin();
		$this->shutdown_info_on(0);				//抑制输出页面底部统计
	}
	
	public function action_index(){		
		$this->action_my();
	}
	
	/**
	 * 我的投票
	 */
	public function action_my(){
		$myvotes = new Model_Base('fg__vote',array('Uid'=>$_SESSION['uid']),'*');
		$this->shutdown_info_on(0);				//抑制输出页面底部统计
		$data = array('myvote'=>$myvotes);
		$data = $this->bind($data)->view('my')->data();		//生成子模块
		$data = array('title'=>"投票系统--我发起的投票",'data'=>$data);
		$page = new Controller_Index();
		$page->action_index($data);				//依赖主页输出
	}
	
	/**
	 * 我参与的投票
	 */
	public function action_voted(){
		$votes_records = new Model_Base('fg__vote_records',array('Uid'=>$_SESSION['uid']),'distinct(`Vid`)');
		if($votes_records->total()>0){
			$voted_ids = array();
			while($votes_records->fetch()){
				$voted_ids []= $votes_records->v('Vid');
			}			
			$hasvoted = new Model_Base('fg__vote',array('`Id` in ('.implode(",", array_fill(0,count($voted_ids),'?')).')'=>$voted_ids),'`Id`,`Name`,`VoteNum`');
		}
		$data = array('myvote'=>isset($hasvoted)?$hasvoted:null);
		$data = $this->bind($data)->view('voted')->data();		//生成子模块
		$data = array('title'=>"投票系统--我参与的投票",'data'=>$data);
		$page = new Controller_Index();
		$page->action_index($data);								//依赖主页输出
	}
	
	/**
	 * 查看投票
	 */
	public function action_view(){
		$id = intval(t::get('id'));
		if($id< 1){
			$data = 'ID传递错误,请检查!';
		}else{
			$vote = new Model_Base('fg__vote',array('Id'=>$id),'*');
			if($vote->v('Id')){
				$this->shutdown_info_on(0);								//抑制输出页面底部统计
				$creator = new Model_Base('fg__user',array('Id'=>$vote->v('Uid')),'Name');
				$data = array('vote'=>$vote,'creator'=>$creator->v("Name"),'access'=>$this->canIVote($id));
				$data = $this->bind($data)->view('view')->data();		//生成子模块				
			}else{
				$data = 'ID传递错误,请检查!';
			}			
		}
		$data = array('title'=>"投票系统--我参与的投票",'data'=>$data);
		$page = new Controller_Index();
		$page->action_index($data);										//依赖主页输出
	}
	
	/**
	 * 添加投票
	 */
	public function action_add(){
		if(t::get('op')=='ajax'){
			$err = array();
			if(mb_strlen(t::post('name'),'UTF8')<5 || mb_strlen(t::post('name'),'UTF8')>30){
				$err []= "投票名称应为5~30个字符!";
			}
			if(mb_strlen(t::post('description'))>200){
				$err []= "投票描述请限制在200字符内!";
			}
			if(!is_array(t::post('options')) || count(t::post('options'))<1){
				$err []= "您没有添加投票选项!";
			}
			if(strtotime(t::post('datebegin')) < strtotime(date('Y-m-d 00:00:00'))){
				var_dump(strtotime(t::post('datebegin')) , strtotime(date('Y-m-d 00:00:00')));
				$err []= "您填写的开始日期应该不早于今天!";
			}
			if(intval(t::post('daylast'))<1 || intval(t::post('daylast'))>30){
				$err []= "投票时间应该在1到30天!";
			}
			if(intval(t::post('votetype'))!=0 && (intval(t::post('picklimit'))<2 || intval(t::post('picklimit'))>count(t::post('options')))){
				$err []= "多选项数应该大于2并且小于现有选项数!";
			}
			if($err){
				$this->json(array('succeed'=>0,'msg'=>implode('<br/>', $err)));
			}
			$votetype = in_array(t::post('votetype'),array(0,1,2))?t::post('votetype'):0;
			$data = array(
				'Name'=>t::post('name'),
				'Uid'=>$_SESSION['uid'],
				'Description'=>t::post('description'),
				'VoteType'=>$votetype,
				'PickLimit'=>$votetype == 0 ? 1 : t::post('picklimit'),
				'BeginTime'=>strtotime(t::post('datebegin')),
				'DayLast'=>t::post('daylast'),
				'Options'=>json_encode(t::post('options')),
				'Result'=>$this->calcResult(count(t::post('options'))),
				'CreateTime'=>time()
			);
			$vote = new Model_Base('fg__vote',$data);
			if($id = $vote->insert()){
				$this->json(array('succeed'=>1,'data'=>$id));
			}else{
				$this->json(array('succeed'=>0,'msg'=>"投票添加失败,请重试!"));
			}
		}
		$data = $this->view('add')->data();		//生成子模块
		$data = array('title'=>"投票系统--我发起的投票",'data'=>$data);
		$page = new Controller_Index();
		$page->action_index($data);
	}
	
	/**
	 * 编辑投票
	 */
	public function action_edit(){		
		if(t::get('op')=='ajax'){
			$err = array();
			$id = intval(t::post('id'));
			if($id == 0){
				$this->json(array('succeed'=>0,'msg'=>"ID参数有误!"));
			}
			$vote = new Model_Base('fg__vote',array('Id'=>$id),'Id,Name,Uid,BeginTime');
			if(!$vote->v('Id')){
				$this->json(array('succeed'=>0,'msg'=>"ID参数有误!"));
			}
			if($vote->v('Uid') != $_SESSION['uid']){
				$this->json(array('succeed'=>0,'msg'=>"您无权编辑别人的投票!"));
			}
			if($vote->v('BeginTime') < time()){
				$this->json(array('succeed'=>0,'msg'=>"此投票已开始,不能修改,你可以选择删除后重新建立投票!"));
			}			
		
			if(mb_strlen(t::post('name'),'UTF8')<5 || mb_strlen(t::post('name'),'UTF8')>30){
				$err []= "投票名称应为5~30个字符!";
			}
			if(mb_strlen(t::post('description'))>200){
				$err []= "投票描述请限制在200字符内!";
			}
			if(!is_array(t::post('options')) || count(t::post('options'))<1){
				$err []= "您没有添加投票选项!";
			}
			if(strtotime(t::post('datebegin')) < strtotime(date('Y-m-d 00:00:00'))){
				var_dump(strtotime(t::post('datebegin')) , strtotime(date('Y-m-d 00:00:00')));
				$err []= "您填写的开始日期应该不早于今天!";
			}
			if(intval(t::post('daylast'))<1 || intval(t::post('daylast'))>30){
				$err []= "投票时间应该在1到30天!";
			}
			if(intval(t::post('votetype'))!=0 && (intval(t::post('picklimit'))<2 || intval(t::post('picklimit'))>count(t::post('options')))){
				$err []= "多选项数应该大于2并且小于现有选项数!";
			}
			if($err){
				$this->json(array('succeed'=>0,'msg'=>implode('<br/>', $err)));
			}
			$votetype = in_array(t::post('votetype'),array(0,1,2))?t::post('votetype'):0;
			$data = array(
				'Name'=>t::post('name'),
				'Uid'=>$_SESSION['uid'],
				'Description'=>t::post('description'),
				'VoteType'=>$votetype,
				'PickLimit'=>$votetype == 0 ? 1 : t::post('picklimit'),
				'BeginTime'=>strtotime(t::post('datebegin')),
				'DayLast'=>t::post('daylast'),
				'Options'=>json_encode(t::post('options')),
				'Result'=>$this->calcResult(count(t::post('options'))),
				'CreateTime'=>time()
			);
			$vote = new Model_Base('fg__vote',$data);
			if($vote->update(array('Id'=>$id))!==false){
				$this->json(array('succeed'=>1,'data'=>$id));
			}else{
				$this->json(array('succeed'=>0,'msg'=>"投票更新失败,请重试!"));
			}
		}
		$error = array();
		$id = intval(t::get('id'));
		if($id == 0){
			$error []="ID参数有误!";
		}else{
			$vote = new Model_Base('fg__vote',array('Id'=>$id),'*');
			if(!$vote->v('Id')){
				$error []="ID参数有误!";
			}else{
				if($vote->v('Uid') != $_SESSION['uid']){
					$error []= "您无权编辑别人的投票!";
				}else{
					if($vote->v('BeginTime') < time()){
						$error []= "此投票已开始,不能修改,你可以选择删除后重新建立投票!";
					}
				}				
			}			
		}		
		$data = $this->bind('vote',isset($vote)?$vote:'')->bind('error',$error)->view('edit')->data();		//生成子模块
		$data = array('title'=>"投票系统--编辑投票",'data'=>$data);
		$page = new Controller_Index();
		$page->action_index($data);
	}
	
	/**
	 * 删除投票
	 */
	public function action_del(){
		$id = intval(t::get('id'));
		if($id == 0){
			$this->redirect("ID参数有误!",BASE_URL."/?c=vote&a=my&rand=".rand());
		}
		$vote = new Model_Base('fg__vote',array('Id'=>$id,'Uid'=>$_SESSION['uid']),'Id');
		if(!$vote->total()){
			$this->redirect("此投票不存在或你无权删除!",BASE_URL."/?c=vote&a=my&rand=".rand());
		}
		if($vote->delete()===false){
			$this->redirect("删除失败!",BASE_URL."/?c=vote&a=my&rand=".rand());
		}else{
			$this->redirect("删除成功!",BASE_URL."/?c=vote&a=my&rand=".rand());
		}
	}
	
	/**
	 * 投票(Ajax)
	 */
	public function action_vote(){
		$id = intval(t::post('id')); $picked = t::post('picked');
		if($id< 1 || !is_array($picked) || empty($picked)){
			$this->json(array("succeed"=>0,'msg'=>"ID参数有误!请重试!"));
		}else{
			$right = $this->canIVote($id);									//检测是否能投票
			if($right['access']){
				$vote = new Model_Base('fg__vote',array('Id'=>$id),'Id,`Result`,`VoteNum`,`Options`,`VoteType`,`PickLimit`');
				if($vote->v('Id')){
					array_unique($picked);
					if(count($picked)>$vote->v('PickLimit')){
						$this->json(array("succeed"=>0,'msg'=>"此投票限投".$vote->v('PickLimit')."项,请检查!"));
					}
					/* 改在独立方法中检测
					$options = json_decode($vote->v('Options'),true);
					foreach ($picked as $k=>$v) {
						if(!isset($options[$v])){
							unset($picked[$k]);
							//$this->json(array("succeed"=>0,'msg'=>"检测到违法传入!"));
						}
					}*/
					$vote->v('Result',$this->calcResult(0,$picked,$vote->v('Result')))
						->v('VoteNum',$vote->v('VoteNum')+1);					
					//var_dump($vote->stack());
					
					$v_record = new Model_Base('fg__vote_records',
						array('Uid'=>$_SESSION['uid'],'Ip'=>ip2long(t::get_ip()),'Vid'=>$id,
							'Picked'=>implode(',',$picked),'CreateTime'=>time()));
					
					$vote->autocommit(false);	//开始事务处理	
					$res1 = $vote->update();
					$res2 = $v_record->insert();
					if($res1!==false && $res2!==false){
						$vote->commit();
						$vote->autocommit(true);
						$this->json(array("succeed"=>1));
					}else{
						//var_dump($res1 , $res2);
						$vote->rollback();
						$vote->autocommit(true);
						$this->json(array("succeed"=>0,'msg'=>"投票失败,请重试!"));
					}
				}else{
					$this->json(array("succeed"=>0,'msg'=>"ID参数有误!请重试!"));
				}	
			}else{
				$this->json(array("succeed"=>0,'msg'=>$right['reason']));
			}
					
		}
	}
	
	/**
	 * 验证我是否能投某个投票
	 * @param	$vid	Int	投票ID
	 */
	static function canIVote($vid=0){
		if(!isset($_SESSION['uid'])){
			return array('access'=>false,'reason'=>"您尚未登陆!");
		}
		$vote = new Model_Base('fg__vote',array('Id'=>$vid),'`Id`,`BeginTime`,`DayLast`');
		if($vote->v('Id')){
			if($vote->v('BeginTime') > time()){
				return array('access'=>false,'reason'=>"此投票尚未开始!");
			}
			if($vote->v('BeginTime')+3600*24*$vote->v('DayLast') < time()){
				return array('access'=>false,'reason'=>"此投票已经结束!");
			}			
			$uid_voted = new Model_Base('fg__vote_records',array("`Uid`=? and `Vid`=?"=>array($_SESSION['uid'],$vid)),"Id");
			if($uid_voted->v('Id')){
				return array('access'=>false,'reason'=>"您已经投过票了!");
			}
			$ip = ip2long(t::get_ip());
			$ip_voted = new Model_Base('fg__vote_records',array("`Ip`=? and `Vid`=?"=>array($ip,$vid)),"Id");
			if($ip_voted->total()>4){
				return array('access'=>false,'reason'=>"您使用的IP地址投票超过5次了!");
			}
		}else{
			return array('access'=>false,'reason'=>"此投票(已)不存在!");
		}
		return array('access'=>true);
	}
	
	/**
	 * 计算投票结果
	 * @param	$total 	int		总选项数
	 * @param	$picked	Array	选取项
	 * @param	$before	String	原结果json串
	 * @return	String	新结果json串
	 */
	private function calcResult($total=10,$picked=array(1),$before=""){
		if($before){
			$before_arr = json_decode($before,true);
			array_unique($picked);
			foreach ($picked as $v) {
				if(isset($before_arr[$v])){
					$before_arr[$v] += 1;
				}				
			}
			return json_encode($before_arr);
		}else{	//生成初始结果json串
			return json_encode(array_fill(0,$total,0));
		}
	} 
}